var iframeCallbackFunction;
var iframeCallbackObject;
var ajajform_global_options={language: "en"};
var ajajform_htmltemplates={};

function ajajform_iframe_call(data)
{
	iframeCallbackObject[iframeCallbackFunction](data);
}

function ajajform_set_global(k,v)
{
	ajajform_global_options[k]=v;
}

(function( $, undefined ) {
if ($.widget) {
$.widget("ui.ajajform", {
	/**
	 *	Class: ui.ajajform
	 *		Создает форму для отправки через ajaj или iframe
	 * Properties:
	 *		options typeof Object 									- Настройки ajajform
	 *		options.cssclass typeof String, default 'ajajform' 					- CSS класс добавляемый к DIV формы
	 *		options.labelwidth typeof integer, default '200' 					- Ширина описания по-умолчанию
	 *		options.inputwidth typeof String, default '200' 					- Ширина форм ввода по-умолчанию
	 *		options.name typeof String, default 'frm' 						- Название формы по-умолчанию
	 *		options.layouttemplate typeof HtmlString, default '<div class="af-body"></div>'		- Расположение элементов внутри формы
	 *		options.languages typeof Array, default []						- языки (?)
	 *		options.readonly typeof boolean,	default false					- без отправки
	 *		options.header typeof String 		- заголовок - отображаемое название формы
	 *		options.submit typeof Object 		- параметры субмита
	 *		options.submit.url typeof String 	- ссылка передачи формы
	 *		options.submit.value typeof String 	- надпись на кнопке сабмита
	 *		options.submit.ajaj typeof boolean 	- передача в режиме ajaj (возвращает реузультат работы prerun_output)
	 *		options.submit.params typeof Object 	- параметры передаваемые формой
	 *		options.submit.xpath typeof String - селектор, куда вставлять кнопку, а если это false - то в стандартный кнопочный футер
	 */
	options: {
		cssclass: "ajajform",
		labelwidth: 200,
		inputwidth: 200,
		name: "frm",
		layouttemplate: '<div class="af-body"></div>',
		languages: [],	
		readonly: false
	},
	/**
	 * Method: _create
	 *		Создает форму, добавляет класс из this.options.cssclass
	 *		добавляет в форму шаблон из this.options.layouttemplate
	 *		обновляет заголовок
	 * Parameters:
	 * Returns:
	 */
	_create: function() {
		var self=this;
		this.element.addClass(this.options.cssclass);
		var frm=document.createElement("form");
		this.element.append(frm);
		frm.onsubmit=function(e) {
			if (self.options.debug) console.log("ajajform.frm.onsubmit(): clicked");
			if (self.options.readonly) return false;
			if (self.allow_submit) return true;
			self.submitClicked(e);
			return false;
		};
		this.frm=frm;
		$("form",this.element).append(this.options.layouttemplate);
		this.refreshHeader();
		this.refreshSubmit();
		this.widgets={};
		this.iframeFrm=null;
		this.alreadyNotValid=false;
	},
	/**
	 * Method: _setOption
	 *		Устанавливает значение и вызвывает refresh, если он есть
	 * Parameters:
	 *		key typeof String		- Название параметра
	 *		value				- Значение параметра
	 * Returns:
	 */
	_setOption: function(key,value) {
		this.options[key]=value;
		var k1=key.substr(0,1);
		var k2=key.substr(1);
		var n="refresh"+k1.toUpperCase()+k2;
		if (this[n]) this[n]();
	},
	/**
	 * Method: _getParams
	 *		Устанавливает значение и вызвывает refresh, если он есть
	 * Parameters:
	 *		key typeof String		- Название параметра
	 *		value				- Значение параметра
	 * Returns:
	 */
	getParams: function() {
		var r={};
		var r2={};
		for (var k in this.options.submit.params) r[k]=this.options.submit.params[k];
		for (var widgetName in this.widgets) {
			var n='#'+this.options.name+'-'+widgetName;
			var w=$(n,this.element);
			w[this.widgets[widgetName]]("postvalue",r,r2);
//			if (!isAjaj) w[this.widgets[widgetName]]("postvalueFile",r2);
		};
		return r;
	},
	/**
	 * Method: refreshHeader
	 *		Обновляет заголовок формы
	 * Parameters:
	 * Returns:
	 */
	refreshHeader: function() {
		if (this.options.header!=null) {
			var a=$(".af-header",this.element);
			if (a.length) {
				a.text(this.options.header);
			} else {
				$(this.frm).prepend("<h1 class='af-header'>"+this.options.header+"</h1>");
			}
		} else {
			$(".af-header",this.element).remove();
		}
	},
	/**
	 * Method: insertWidget
	 *		Вставляет widget
	 * Parameters:
	 * 	 	layoutDivId typeof selector 		- Селектор вставки
	 *		beforeWidgetName typeof String		- Не используется
	 *		widgetOptions typeof Object		- Параметры виджета
	 *		widgetOptions.name typeof String	- Имя
	 *		widgetOptions.xpath typeof selector	- Селектор
	 *		widgetOptions.type typeof string	- Тип инпута
	 * Returns:
	 * 		typeof Function 			- Инизиализация вставленного виджета
	 */
	insertWidget: function(layoutDivId,beforeWidgetName,widgetOptions) {
		if (!layoutDivId) layoutDivId=widgetOptions.xpath||".af-body";
		var widgetName=widgetOptions.name;
		if (this.widgets[widgetName]) {
			console.log("Element exists "+widgetOptions.name+"/"+widgetOptions.type);
			return undefined;
		}
		var el;
		el=$(layoutDivId,this.element);
		if (el.length==0) console.log("No xpath element "+layoutDivId+" for element "+widgetOptions.name+"/"+widgetOptions.type);
		var t="ajajform_"+widgetOptions.type;
		var n=this.options.name+'-'+widgetName;
		this.widgets[widgetName]=t;
		if (this.options.readonly) widgetOptions.readonly=true;
		widgetOptions.tagid=n;
		return $("<div id='"+n+"'></div>").appendTo(el)[t](widgetOptions);
	},
	/**
	 * Method: deleteWidget
	 *		удаляет widget
	 * Parameters:
	 *		widgetName typeof String		- Имя виджета
	 * Returns:
	 */

	deleteWidget: function(widgetName) {
		if (!this.widgets[widgetName]) return;
		
		var n='#'+this.options.name+'-'+widgetName;
		var w=$(n,this.element);
		w[this.widgets[widgetName]]("destroy");
		w.remove();
		delete this.widgets[widgetName];
	},
	
	/**
	 * Method: deleteWidgetsInLayoutBlock
	 *		удаляет widget'ы из указанного блока
	 * Parameters:
	 *		layoutDivId typeof String		- селектор блока
	 * Returns:
	 */

	deleteWidgetsInLayoutBlock: function(layoutDivId) {
//		$("#debug").append("<div>deleteWidgetsInLayoutBlock</div>");
		for (var widgetName in this.widgets) {
			var n='#'+this.options.name+'-'+widgetName;
//			$("#debug").append("<div>n="+n+"</div>");
			if ($(layoutDivId+" "+n,this.element).length) this.deleteWidget(widgetName);
		}
	},
	/**
	 * Method: refreshFooterButtons
	 *		обновление кнопок в футере
	 * Parameters:
	 * Returns:
	 */
	refreshFooterButtons: function() {
		var arr=this.options.footerButtons?this.options.footerButtons.slice():new Array();
		if (this.options.submit && !this.options.readonly) arr.push(this.options.submit);
		if (arr.length==0) {$(".af-buttons",this.element).remove();return;}
		var a=$(".af-buttons",this.element);
		if (a.length==0) a=$('<div class="af-buttons"></div>').appendTo(this.frm).css("padding-left",this.options.labelwidth); else a.empty();
		for (var i=0;i<arr.length;i++) {
			var isSubmit=(i+1==arr.length && this.options.submit);
			var b=$(isSubmit?"<input type='button'/>":"<input type='button'/>").appendTo(arr[i].xpath ? arr[i].xpath : a);
			b.prop("value",arr[i].value!=null?arr[i].value:"Submit");
//			b.text(arr[i].value!=null?arr[i].value:"Submit");
			b.button();
			if (arr[i].cssclass) b.addClass(arr[i].cssclass);
//			b.bind("click",{button: arr[i], t: this, func:isSubmit?"submitClicked":"buttonClicked"},function(e) { e.data.t[e.data.func](e,e.data.button); });
			if (isSubmit) {
				b.bind("click",{button: arr[i], t: this},function(e) { e.data.t.submitClicked(e,e.data.button); return false; });
//				b.bind("click",{t:this}, function(e) { $(e.data.t.frm).submit(); });
			} else {
				b.bind("click",{button: arr[i], t: this},function(e) { e.data.t.buttonClicked(e,e.data.button); });
			}
		}
	},
	/**
	 * Method: refreshSubmit
	 *		Обновляет submit
	 * Parameters:
	 * Returns:
	 */
	refreshSubmit: function() {
		this.refreshFooterButtons();
	},
	/**
	 * Method: validateForm
	 *		Валидация формы
	 * Parameters:
	 * Returns:
	 * 		typeof boolean - Прошла ли валидация
	 */
	validateForm: function() {
		var all=false;
		var err="";
		for (var widgetName in this.widgets) {
			var n='#'+this.options.name+'-'+widgetName;
			var w=$(n,this.element);
			var item=w[this.widgets[widgetName]]("validate");
			if (item) {
				if (this.options.debug) console.log("validate fails: "+n+" ("+this.widgets[widgetName]+")");
				all=true;
				err+="\n";
				n=w[this.widgets[widgetName]]("option","label");
				var tag=w[0];
				var tabid;
				while (tag) {
					if ($(tag).attr("aria-labelledby")) tabid=$(tag).attr("aria-labelledby");
					if (tabid) {
						var a=$(".afw-accordion > div > ul > li[aria-labelledby='"+tabid+"'] > a");
						if (a.length) n=a.text()+" > "+n;
						tabid=undefined;
					}
					tag=tag.parentNode;
				}
        if (typeof(n) == "object") {
          console.log(n);
        }
				err+=n;
			}
		}
		if (all && this.alreadyNotValid) {
			alert("These fields are incorrect:"+err);
		}
		return !all;
	},

	setInProgress: function(state) {
		this.inprogress=false;
		var frm=$("form",this.element);
		$("input",frm).not(".fileInput").prop("disabled",state?true:false).removeClass("ui-state-hover");
		$("select",frm).prop("disabled",state?true:false);
		$("textarea",frm).prop("disabled",state?true:false);
	},

	/**
	 * Method: submitClicked
	 *		Обработка нажатия на submit - собирает все значения виджетов внутри формы и делает запрос 
	 * Parameters:
	 * 		e typeof  Object
	 * Returns:
	 * 		typeof boolean
	 */
	submitClicked: function(e) {
		var t=this;
		if (this.inprogress) return;
		if (this.options.debug) console.log("ajajform.submitClicked(): clicked");
		if (this.options.readonly) {
			if (this.options.debug) console.log("ajajform.submitClicked(): form is read-only");
			return false;
		}
		if (!this.validateForm()) {
			if (this.options.debug) console.log("ajajform.submitClicked(): validate fails");
			this.alreadyNotValid=true;
			return false;
		}
		this.alreadyNotValid=false;
		var r={};
		var r2={};
		if (this.options.submit.params) {
			for (var k in this.options.submit.params) r[k]=this.options.submit.params[k];
		}
		var isAjaj=this.options.submit.ajaj;
		for (var widgetName in this.widgets) {
			var n='#'+this.options.name+'-'+widgetName;
			var w=$(n,this.element);
			w[this.widgets[widgetName]]("postvalue",r,r2);
//			if (!isAjaj) w[this.widgets[widgetName]]("postvalueFile",r2);
		}
		if (this.options.submit.click) {
			if (!this.options.submit.click(r,r2)) {
				if (this.options.debug) console.log("ajajform.submitClicked(): this.options.submit.click() fails");
				return false;
			}
		}
		for (var tmp in r2) isAjaj=false;
		if (r2.length) isAjaj=false;
		if (isAjaj) {
			if (this.options.debug) console.log("ajajform.submitClicked(): submitting via ajax");
			$.ajax({
				type: "POST",
				url: this.options.submit.url,
				data: r,
				error: function(jqXHR, textStatus, errorThrown) { t.inprogress=0; t.submitResponse(jqXHR.responseText); },
				success: function(a) { t.inprogress=0; t.submitResponse(a);}
			});
		} else {
			if (this.options.debug) console.log("ajajform.submitClicked(): sending to iframe");
			this.mkIframeForm();
			var frm=$("form",this.element);
			$("input",frm).not(".fileInput").prop("disabled",true);
			$("select",frm).prop("disabled",true);
			$("textarea",frm).prop("disabled",true);
			$(".autoAdded",frm).remove();
			this.fillObjectToForm(frm,r,false);
//			this.fillObjectToForm(frm,r2,true); Input objects must already be
			this.addInput(frm,"hidden","is-iframe","1");
			this.addInput(frm,"hidden","iframe-response","ajajform_iframe_call");
			frm.prop("target",this.options.name+'-iframe');
			frm.prop("action",this.options.submit.url);
			frm.prop("method","POST");
			frm.prop("enctype","multipart/form-data");
			this.allow_submit=true;
			frm.submit();
			iframeCallbackFunction="submitResponse";
			iframeCallbackObject=this;
		}
		return false;
	},
	/**
	 * Method: submitResponse
	 *		 Запускает std_response
	 * Parameters:
	 * 		rtext typeof String - имя функции
	 * Returns:
	 */

	submitResponse: function(rtext) {
		var frm=$("form",this.element);
		$("input",frm).not(".fileInput").prop("disabled",false);
		$("select",frm).prop("disabled",false);
		$("textarea",frm).prop("disabled",false);
		if (typeof rtext!=="object") {
			try {
				rtext=JSON.parse(rtext);
			} catch (e) {
				std_response(rtext);
				return;
			}
		}
		if (rtext.form_errors) {
			for (var widgetName in rtext.form_errors) {
				var n='#'+this.options.name+'-'+widgetName;
				var w=$(n,this.element);
				if (this.widgets[widgetName]) {
					w[this.widgets[widgetName]]("setError",rtext.form_errors[widgetName]);
				} else {
					console.log("input does not exists - "+widgetName);
				}
			}
			return;
		}
		std_response(rtext);
	},
	/**
	 * Method: getWidgets
	 *		Возвращает селекторы всех виджетов
	 * Parameters:
	 * Returns:
	 * 		typeof Object
	 */
	getWidgets: function() {
		return this.widgets;
	},
	/**
	 * Method: getWidget
	 *		Возвращает селектор виджет
	 * Parameters:
	 * 		widgetName typeof  String - имя виджета
	 * Returns:
	 * 		typeof selector
	 */
	getWidget: function(widgetName) {
		var n='#'+this.options.name+'-'+widgetName;
		var w=$(n,this.element);
		return w;
//		return w[this.widgets[widgetName]];
	},
	/**
	 * Method: getWidgetValue
	 *		Возвращает значение виджета
	 * Parameters:
	 * 		widgetName typeof  String - имя виджета
	 * Returns:
	 * 		typeof something
	 */
	getWidgetValue: function(widgetName) {
		var r={};
		var n='#'+this.options.name+'-'+widgetName;
		var w=$(n,this.element);
		w[this.widgets[widgetName]]("postvalue",r);
		return r[widgetName];
	},
	/**
	 * Method: getWidgetOption
	 *		Возвращает значение параметра виджета
	 * Parameters:
	 * 		widgetName typeof  String - имя виджета
	 * 		k typeof  String	  - имя параметра 
	 * Returns:
	 * 		typeof something
	 */
	getWidgetOption: function(widgetName,k) {
		var n='#'+this.options.name+'-'+widgetName;
		var w=$(n,this.element);
		return w[this.widgets[widgetName]]("option",k);
	},
	/**
	 * Method: setWidgetOption
	 *		Устанавливает значение параметра виджета
	 * Parameters:
	 * 		widgetName typeof  String - имя виджета
	 * 		k typeof  String	  - имя параметра
	 * 		r typeof  something	  - значение параметра
	 * Returns:
	 */
	setWidgetOption: function(widgetName,k,r) {
		var n='#'+this.options.name+'-'+widgetName;
		var w=$(n,this.element);
		w[this.widgets[widgetName]]("option",k,r);
	},	
	/**
	 * Method: setWidgetValue
	 *		Устанавливает значение виджета
	 * Parameters:
	 * 		widgetName typeof  String - имя виджета
	 * 		r typeof  something	  - имя значения
	 * Returns:
	 */
	setWidgetValue: function(widgetName,r) {
		var n='#'+this.options.name+'-'+widgetName;
		var w=$(n,this.element);
		if (w.length==0) return;
		w[this.widgets[widgetName]]("option","value",r);
		w[this.widgets[widgetName]]("validate");
	},
	/**
	 * Method: fillObjectToForm
	 *		 Добавляет несколько инпутов из объекта типа hidden либо file 
	 * Parameters:
	 *		form typeof  selector	  - селектор формы
	 * 		obj typeof  Object	  - объект с инпутами
	 * 		isFile typeof  boolean	  - файл?
	 * Returns:
	 */
	fillObjectToForm: function(form,obj,isFile) {
		var t=isFile?"file":"hidden";
		for (var k in obj) {
			var v=obj[k];
			if (v==undefined) {
				this.addInput(form,t,k,"");
			} else if (v==null) {
				this.addInput(form,t,k,"");
			} else if (v.constructor==Array) {
				for (var i=0;i<v.length;i++) this.addInput(form,t,k,v[i]);
			} else {
				this.addInput(form,t,k,v);
			}
		}
	},
	/**
	 * Method: addInput
	 *		Добавить тег input в form
	 * Parameters:
	 * 		form typeof  selector	  - селектор формы
	 * 		type typeof  String	  - тип инпута
	 * 		k typeof  name	 	  - имя инпута
	 * 		v typeof  something	  - значение
	 * Returns:
	 */
	addInput: function(form,type,k,v) {
		if (type=="file") {
			$('<input class="autoAdded" type="'+type+'" name="'+k+'"value="'+v+'"/>').appendTo(form);
		} else {
			$('<input class="autoAdded" type="'+type+'"/>').appendTo(form).prop("name",k).val(v);
		}
	},	
	/**
	 * Method: buttonClicked
	 *		Обработка нажатия на кнопку
	 * Parameters:
	 * 		e typeof  Event - событие клика
	 * 		button typeof  Object - параметры кнопки
	 * Returns:
	 */
	buttonClicked: function(e,button) {
		if (button.click) {
			if (!button.click()) return;
		}
		if (button.url) {
			document.location=button.url;
		}
	},
	/**
	 * Method: getSubmitParam
	 *		Вовзращает значение параметра отправки
	 * Parameters:
	 * 		p typeof  String - имя параметра
	 * Returns:
	 * 		typeof something
	 */
	getSubmitParam: function(p) {
		return this.options.submit.params[p];
	},
	/**
	 * Method: setSubmitParam
	 *		Устанавливает и возвращает значение параметра отправки
	 * Parameters:
	 * 		p typeof  String - имя параметра
	 * 		v typeof  something - значение параметра
	 * Returns:
	 * 		typeof something - значение параметра
	 */
	setSubmitParam: function(p,v) {
		return this.options.submit.params[p]=v;
	},
	/**
	 * Method: destroy
	 *	 не используется
	 * Parameters:
	 * Returns:
	 */
	destroy: function() {
	},
	/**
	 * Method: mkIframeForm
	 *		Создание iframe формы
	 * Parameters:
	 * Returns:
	 */
	mkIframeForm: function() {
		if (this.iframe) return;
		var iframe=$('<iframe name="'+this.options.name+'-iframe" id="'+this.options.name+'-iframe" frameborder="0"></iframe>').appendTo(this.element);
//		this.iframeForm=$('<form name="'+this.options.name+'-iframe-form"></form>').appendTo(this.element);
//		this.addInput(this.iframeForm,'hidden','is-iframe','1');
	}

});
}
})( jQuery );

function ajajform_frm_set_id(data)
{
	frm.ajajform("setSubmitParam",data.name,data.id);
}

